{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-09-17T02:18:11.484797Z",
     "start_time": "2025-09-17T02:18:05.344262Z"
    }
   },
   "source": [
    "import d2l.torch\n",
    "import torch\n",
    "import torchvision\n",
    "from torch import nn\n",
    "from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten\n",
    "from torch.utils.data import DataLoader\n",
    "from torch.utils.tensorboard import SummaryWriter\n",
    "from torchvision import transforms\n",
    "\n",
    "import time\n",
    "\n",
    "# 将图像数据进行归一化处理，使得模型更容易收敛\n",
    "transform = transforms.Compose([\n",
    "\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n",
    "])\n",
    "\n",
    "train_data = torchvision.datasets.CIFAR10(root='../dataset', train=True, download=True, transform=transform)\n",
    "train_loader = DataLoader(train_data, batch_size=64, shuffle=True)\n",
    "\n",
    "test_data = torchvision.datasets.CIFAR10(root='../dataset', train=False, download=True, transform=transform)\n",
    "test_loader = DataLoader(test_data, batch_size=64, shuffle=True)\n",
    "\n",
    "print(f\"训练集的长度为：{len(train_data)}\")\n",
    "print(f\"测试集的长度为：{len(test_data)}\")\n",
    "print(f\"特征尺度为:{train_data[0][0].shape}\")\n",
    "device = torch.device(\"mps\" if torch.backends.mps.is_available() else \"cpu\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集的长度为：50000\n",
      "测试集的长度为：10000\n",
      "特征尺度为:torch.Size([3, 32, 32])\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-17T02:18:15.198462Z",
     "start_time": "2025-09-17T02:18:15.169955Z"
    }
   },
   "cell_type": "code",
   "source": [
    "drop = 0.4\n",
    "def nin_block(in_channels, out_channels, kernel_size, stride, padding):\n",
    "    return Sequential(\n",
    "        Conv2d(in_channels, out_channels, kernel_size=kernel_size, padding=padding, stride=stride),\n",
    "        nn.ReLU(inplace=True),\n",
    "        Conv2d(out_channels, out_channels, kernel_size=1),\n",
    "        nn.ReLU(inplace=True),\n",
    "        Conv2d(out_channels, out_channels, kernel_size=1),\n",
    "        nn.ReLU(inplace=True),\n",
    "    )\n",
    "class NiN(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(NiN, self).__init__()\n",
    "        self.model = nn.Sequential(\n",
    "            nin_block(3, 96, kernel_size=3, stride=1, padding=1),\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "            nin_block(96, 256, kernel_size=3, stride=1, padding=2),\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "            nin_block(256, 384, kernel_size=3, stride=1, padding=2),\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "            nn.Dropout(drop),\n",
    "            nin_block(384, 10, kernel_size=3, stride=1, padding=2),\n",
    "            nn.AdaptiveAvgPool2d((1, 1)),\n",
    "            nn.Flatten(),\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.model(x)\n",
    "\n",
    "model = NiN().to(device)\n",
    "print(model)"
   ],
   "id": "b1e0d0cf324f7992",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NiN(\n",
      "  (model): Sequential(\n",
      "    (0): Sequential(\n",
      "      (0): Conv2d(3, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "      (1): ReLU(inplace=True)\n",
      "      (2): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (3): ReLU(inplace=True)\n",
      "      (4): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (5): ReLU(inplace=True)\n",
      "    )\n",
      "    (1): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
      "    (2): Sequential(\n",
      "      (0): Conv2d(96, 256, kernel_size=(3, 3), stride=(1, 1), padding=(2, 2))\n",
      "      (1): ReLU(inplace=True)\n",
      "      (2): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (3): ReLU(inplace=True)\n",
      "      (4): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (5): ReLU(inplace=True)\n",
      "    )\n",
      "    (3): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
      "    (4): Sequential(\n",
      "      (0): Conv2d(256, 384, kernel_size=(3, 3), stride=(1, 1), padding=(2, 2))\n",
      "      (1): ReLU(inplace=True)\n",
      "      (2): Conv2d(384, 384, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (3): ReLU(inplace=True)\n",
      "      (4): Conv2d(384, 384, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (5): ReLU(inplace=True)\n",
      "    )\n",
      "    (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
      "    (6): Dropout(p=0.4, inplace=False)\n",
      "    (7): Sequential(\n",
      "      (0): Conv2d(384, 10, kernel_size=(3, 3), stride=(1, 1), padding=(2, 2))\n",
      "      (1): ReLU(inplace=True)\n",
      "      (2): Conv2d(10, 10, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (3): ReLU(inplace=True)\n",
      "      (4): Conv2d(10, 10, kernel_size=(1, 1), stride=(1, 1))\n",
      "      (5): ReLU(inplace=True)\n",
      "    )\n",
      "    (8): AdaptiveAvgPool2d(output_size=(1, 1))\n",
      "    (9): Flatten(start_dim=1, end_dim=-1)\n",
      "  )\n",
      ")\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-17T02:18:51.895035Z",
     "start_time": "2025-09-17T02:18:51.145636Z"
    }
   },
   "cell_type": "code",
   "source": [
    "X = torch.randn(3, 224, 224).to(device)\n",
    "for layer in model.model:\n",
    "    X = layer(X)\n",
    "    print(layer.__class__.__name__, f'output shape:{X.shape}')"
   ],
   "id": "8fc8c3fed170df0e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sequential output shape:torch.Size([96, 224, 224])\n",
      "MaxPool2d output shape:torch.Size([96, 111, 111])\n",
      "Sequential output shape:torch.Size([256, 113, 113])\n",
      "MaxPool2d output shape:torch.Size([256, 56, 56])\n",
      "Sequential output shape:torch.Size([384, 58, 58])\n",
      "MaxPool2d output shape:torch.Size([384, 28, 28])\n",
      "Dropout output shape:torch.Size([384, 28, 28])\n",
      "Sequential output shape:torch.Size([10, 30, 30])\n",
      "AdaptiveAvgPool2d output shape:torch.Size([10, 1, 1])\n",
      "Flatten output shape:torch.Size([10, 1])\n"
     ]
    }
   ],
   "execution_count": 4
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "d2l.torch.load_data_fashion_mnist()",
   "id": "94e44313d740dfc2"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
